//------------------------------------------------------------------------------
//
// Generic Brick Utilities
//
// Written Jan-2008 by Trevor Taylor, Software Technology, Australia
//
// IMPORTANT NOTE:
// See the information in GenericBrickState.cs
//
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Ccr.Core;
using Microsoft.Dss.Core.Attributes;
//using Microsoft.Dss.ServiceModel.Dssp;
//using Microsoft.Dss.ServiceModel.DsspServiceBase;


using brick = ProMRDS.Robotics.GenericBrick.Proxy;

namespace ProMRDS.Robotics.GenericBrickUtil
{
#if !URT_MINCLR

    //[DataContract]
    public class Resources
    {
        // Insert this code into your code to use the transform
        // NOTE: The embedded resource is NOT included in the Proxy DLL!
        // This is the subject of a posting to the Discussion Forum.
        // It is only here for documentation purposes.

        // Add an XSLT file to format the state
        // The filename is appended to the default namespace for this solution
        //[DataMember]
        [EmbeddedResource("ProMRDS.Robotics.GenericBrickUtil.GenericBrick.xslt")]
        public string _transform = null;
    }

#endif

    #region Utility Functions for Devices

    /// <summary>
    /// Utility Functions for Generic Brick
    /// </summary>
    public static class Util
    {
        /// <summary>
        /// Find a Device in a List by Hardware Id
        /// </summary>
        /// <param name="list"></param>
        /// <param name="id"></param>
        /// <returns>Index if found or -1 if not</returns>
        public static int FindDeviceById(List<brick.Device> list, int id)
        {
            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].HardwareIdentifer == id)
                    return i;
            }
            // Not found!
            return (-1);
        }

        /// <summary>
        /// Is this an Analog Device?
        /// </summary>
        /// <param name="dev"></param>
        /// <returns>True if Analog, False if not</returns>
        public static bool IsAnalogDevice(brick.Device dev)
        {
            if (((dev.Type & brick.DeviceTypes.AnalogIn) != 0) ||
                ((dev.Type & brick.DeviceTypes.AnalogOut) != 0))
                return true;
            else
                return false;
        }

        /// <summary>
        /// Is this a Digital Device?
        /// </summary>
        /// <param name="dev"></param>
        /// <returns>True if Digital, False if not</returns>
        public static bool IsDigitalDevice(brick.Device dev)
        {
            if (((dev.Type & brick.DeviceTypes.DigitalIn) != 0) ||
                ((dev.Type & brick.DeviceTypes.DigitalOut) != 0) ||
                ((dev.Type & brick.DeviceTypes.DigitalInOut) != 0))
                return true;
            else
                return false;
        }

        /// <summary>
        /// Set the corresponding bit in a Bitmask
        /// </summary>
        /// <param name="Bitmask">Current bitmask of states</param>
        /// <param name="IDs">List of IDs - The index is the bit position</param>
        /// <param name="id">ID of the device - Must be in the List of IDs</param>
        /// <param name="state">New State</param>
        /// <returns>Bitmask is updated</returns>
        /// NOTE: Does nothing if id is not found
        public static int UpdateBitmask(int Bitmask, int[] IDs, int id, bool state)
        {
            int mask = 1;
            int newMask = Bitmask;
            for (int i = 0; i < IDs.Length; i++)
            {
                if (id == IDs[i])
                {
                    if (state)
                        newMask = Bitmask | mask;
                    else
                        newMask = Bitmask & (~mask);
                    break;
                }
                mask = mask << 1;
            }
            return newMask;
        }

        /// <summary>
        /// Update the State of a Digital Device
        /// </summary>
        /// <param name="dev"></param>
        /// <param name="state"></param>
        /// <remarks>Use this routine to keep the State and Value fields in sync</remarks>
        public static void UpdateDeviceState(brick.Device dev, bool state)
        {
            dev.State = state;
            if (state)
                dev.Value = 1;
            else
                dev.Value = 0;
            dev.TimeStamp = DateTime.Now;
        }

        /// <summary>
        /// Update the State of a Digital Device in a List of Devices
        /// </summary>
        /// <param name="devlist"></param>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// NOTE: Does nothing if id is not found
        public static void UpdateDeviceStateInList(List<brick.Device> devlist, int id, bool state)
        {
            int n;
            n = FindDeviceById(devlist, id);
            if (n >= 0)
                UpdateDeviceState(devlist[n], state);
        }

        /// <summary>
        /// Update the Value of an Analog Device
        /// </summary>
        /// <param name="dev"></param>
        /// <param name="value"></param>
        /// <remarks>Use this routine to keep the State and Value fields in sync</remarks>
        public static void UpdateDeviceValue(brick.Device dev, double value)
        {
            dev.Value = value;
            if (value != 0)
                dev.State = true;
            else
                dev.State = false;
            dev.TimeStamp = DateTime.Now;
        }

        /// <summary>
        /// Update the Value of an Analog Device in a List of Devices
        /// </summary>
        /// <param name="devlist"></param>
        /// <param name="id"></param>
        /// <param name="value"></param>
        /// NOTE: Does nothing if id is not found
        public static void UpdateDeviceValueInList(List<brick.Device> devlist, int id, double value)
        {
            int n;
            n = FindDeviceById(devlist, id);
            if (n >= 0)
                UpdateDeviceValue(devlist[n], value);
        }

    }

    #endregion

}
